import axios from 'axios';

// API base URL - adjust based on your environment
const API_BASE_URL = process.env.REACT_APP_API_URL || 'http://localhost:8000';

// Create axios instance
const apiClient = axios.create({
  baseURL: API_BASE_URL,
  timeout: 30000, // 30 seconds timeout
  headers: {
    'Content-Type': 'application/json',
  },
});

// Types for API responses
export interface Dataset {
  id: string;
  name: string;
  description?: string;
  file_path: string;
  vector_columns: string[];
  shape: {
    n_samples: number;
    n_dimensions: number;
  };
  created_at: string;
  metadata?: any;
}

export interface Job {
  id: string;
  type: string;
  status: 'pending' | 'running' | 'completed' | 'failed';
  input_dataset_id: string;
  parameters: any;
  result_path?: string;
  error_message?: string;
  created_at: string;
  completed_at?: string;
  metadata?: any;
}

export interface HealthResponse {
  status: string;
  timestamp: string;
  service: string;
}

// API service class
export class AnalyticsAPI {
  // Health check
  async getHealth(): Promise<HealthResponse> {
    const response = await apiClient.get('/health');
    return response.data;
  }

  // Dataset operations
  async uploadDataset(file: File, name: string, vectorColumns: string[], description?: string, fileFormat = 'csv'): Promise<Dataset> {
    const formData = new FormData();
    formData.append('file', file);
    formData.append('name', name);
    formData.append('vector_columns', JSON.stringify(vectorColumns));
    if (description) formData.append('description', description);
    formData.append('file_format', fileFormat);

    const response = await apiClient.post('/api/v1/datasets/upload', formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    });
    return response.data;
  }

  async getDatasets(): Promise<Dataset[]> {
    const response = await apiClient.get('/api/v1/datasets');
    return response.data;
  }

  async getDataset(id: string): Promise<Dataset> {
    const response = await apiClient.get(`/api/v1/datasets/${id}`);
    return response.data;
  }

  async deleteDataset(id: string): Promise<void> {
    await apiClient.delete(`/api/v1/datasets/${id}`);
  }

  // Job operations
  async submitJob(jobData: {
    job_type: string;
    input_dataset_id: string;
    parameters: any;
    name?: string;
  }): Promise<Job> {
    const response = await apiClient.post('/api/v1/jobs/submit', jobData);
    return response.data;
  }

  async getJobs(): Promise<Job[]> {
    const response = await apiClient.get('/api/v1/jobs');
    return response.data;
  }

  async getJob(id: string): Promise<Job> {
    const response = await apiClient.get(`/api/v1/jobs/${id}`);
    return response.data;
  }

  async getJobResult(id: string): Promise<any> {
    const response = await apiClient.get(`/api/v1/jobs/${id}/result`);
    return response.data;
  }

  // Specific job type endpoints
  async submitKMeansJob(datasetId: string, params: {
    k: number;
    max_iter?: number;
    seed?: number;
  }): Promise<Job> {
    const response = await apiClient.post('/api/v1/vector/kmeans', {
      dataset_id: datasetId,
      ...params
    });
    return response.data;
  }

  async submitPCAJob(datasetId: string, params: {
    k: number;
  }): Promise<Job> {
    const response = await apiClient.post('/api/v1/vector/pca', {
      dataset_id: datasetId,
      ...params
    });
    return response.data;
  }

  async submitSimilarityJob(datasetId: string, params: {
    metric?: string;
    threshold?: number;
    sample_size?: number;
  }): Promise<Job> {
    const response = await apiClient.post('/api/v1/vector/similarity', {
      dataset_id: datasetId,
      ...params
    });
    return response.data;
  }

  async submitOutlierDetectionJob(datasetId: string, params: {
    method?: string;
    threshold?: number;
  }): Promise<Job> {
    const response = await apiClient.post('/api/v1/vector/outliers', {
      dataset_id: datasetId,
      ...params
    });
    return response.data;
  }

  async submitStatisticsJob(datasetId: string): Promise<Job> {
    const response = await apiClient.post('/api/v1/vector/statistics', {
      dataset_id: datasetId
    });
    return response.data;
  }

  async submitNearestNeighborsJob(datasetId: string, params: {
    query_vector: number[];
    k?: number;
    metric?: string;
  }): Promise<Job> {
    const response = await apiClient.post('/api/v1/vector/nearest-neighbors', {
      dataset_id: datasetId,
      ...params
    });
    return response.data;
  }

  // Real-time (synchronous) endpoints
  async getVectorStatistics(datasetId: string): Promise<any> {
    const response = await apiClient.post(`/api/v1/vector/statistics/realtime`, {
      dataset_id: datasetId
    });
    return response.data;
  }

  async executeKMeans(datasetId: string, params: {
    k: number;
    max_iter?: number;
    seed?: number;
  }): Promise<any> {
    const response = await apiClient.post(`/api/v1/vector/kmeans/realtime`, {
      dataset_id: datasetId,
      ...params
    });
    return response.data;
  }

  // Geospatial data methods
  async uploadGeospatialDataset(formData: FormData): Promise<Dataset> {
    const response = await apiClient.post('/api/v1/datasets/upload-geospatial', formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    });
    return response.data;
  }

  async getGeospatialMetadata(datasetId: string): Promise<any> {
    const response = await apiClient.get(`/api/v1/datasets/${datasetId}/geospatial-metadata`);
    return response.data;
  }

  async submitSpatialAnalysis(
    datasetId: string,
    endpoint: string,
    params: any
  ): Promise<any> {
    const response = await apiClient.post(endpoint, {
      dataset_id: datasetId,
      ...params
    });
    return response.data;
  }

  async spatialClustering(datasetId: string, params: {
    k?: number;
    max_iter?: number;
    seed?: number;
    include_spatial_metrics?: boolean;
  }): Promise<any> {
    const response = await apiClient.post('/api/v1/spatial/clustering/realtime', {
      dataset_id: datasetId,
      ...params
    });
    return response.data;
  }

  async spatialSimilarity(datasetId: string, params: {
    spatial_weight?: number;
    feature_weight?: number;
    threshold?: number;
    sample_size?: number;
  }): Promise<any> {
    const response = await apiClient.post('/api/v1/spatial/similarity/realtime', {
      dataset_id: datasetId,
      ...params
    });
    return response.data;
  }

  async spatialStatistics(datasetId: string): Promise<any> {
    const response = await apiClient.post('/api/v1/spatial/statistics/realtime', {
      dataset_id: datasetId
    });
    return response.data;
  }
}

// Export singleton instance
export const analyticsAPI = new AnalyticsAPI();

// Export default
export default analyticsAPI;